package cn.hongwei.eduservice.service.impl;

import cn.hongwei.eduservice.entity.Subject;
import cn.hongwei.eduservice.entity.excel.SubjectExcelData;
import cn.hongwei.eduservice.listener.SubjectDataListener;
import cn.hongwei.eduservice.mapper.SubjectMapper;
import cn.hongwei.eduservice.service.SubjectService;
import cn.hongwei.result.ResultCodeEnum;
import cn.hongwei.service.base.handler.GuliException;
import com.alibaba.excel.EasyExcel;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.apache.commons.lang3.exception.ExceptionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author Great
 * @email 1224028994@qq.com
 * 将表格数据导入到数据库
 */
@Service
public class SubjectServiceImpl extends ServiceImpl<SubjectMapper,Subject> implements SubjectService {

    @Autowired
    private SubjectMapper subjectMapper;

    @Override
    public void importSubjects(MultipartFile file) {
        //1、为excel文档创建bean 描述excel和bean的映射关系
        //2、创建监听器： 解析excel并转为对象
        //3、使用asyexcel 读取数据交给监听器使用数据
        try {
            EasyExcel.read(file.getInputStream())
                    .sheet(0)
                    .registerReadListener(new SubjectDataListener(baseMapper))
                    .head(SubjectExcelData.class)
                    .doRead();
        } catch (Exception e) {//ExcelAnalysisException
            //当前捕获异常的为编译时的异常，必须处理，但是如果真的出现了能够捕获的异常，代码正常执行
            //响应给前端的是处理成功
//            e.printStackTrace();
//            throw new RuntimeException(); //将编译异常转为运行异常抛出，当捕获到异常时仍然抛出异常
            //当抛出RuntimeException，全局异常处理器可以单独处理，但是不方便给前端提示异常的原因
            //我们可以自定义一个异常，在异常对象中携带需要描述的异常信息
            log.error(ExceptionUtils.getStackTrace(e));//真正的异常信息
            throw new GuliException(ResultCodeEnum.EXCEL_DATA_IMPORT_ERROR);
        }
    }

    //这个业务好好的理解
    @Override
    public List<Subject> getSubjectsNestedList() {
        //先查询整张表edu_subject
        List<Subject> subjects = baseMapper.selectList(null);

        //创建一个存储一级分类和二级分类对应关系的map key是id value是subject对象
        Map<String,Subject> pmap=new HashMap<>();

        //遍历list集合,取出一级对象,一级对象的parent_id是0
        for (Subject subject : subjects) {
            if("0".equals(subject.getParentId())){
                pmap.put(subject.getId(),subject);
            }
        }
        //经过这个for循环,map中只存储了一级对象,而内部的list(children)没有值

        //再次遍历集合,获取一级分类下对应的二级分类
        for (Subject subject : subjects) {
            if(!"0".equals(subject.getParentId())){
                //这里的subject肯定是二级分类
                /*
                * 从map中取出二级分类:
                *  先通过二级分类的pid,在map中取出对应的一级分类
                *  在通过subject的对象获取内部存储的二级分类集合
                * */
                Subject oneLevel = pmap.get(subject.getParentId());
                List<Subject> children = oneLevel.getChildren();
                //将二级分类添加到这个集合中
                children.add(subject);
            }
        }
        //这两个循环结束以后,map中的数据就是正确的一级分类和二级分类的关系
        return new ArrayList(pmap.values());
    }
}
